home *** CD-ROM | disk | FTP | other *** search
- /* AmiTrack.c -- a program to keep a running list of available Amigas. */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include <exec/types.h>
- #include <exec/io.h>
- #include <exec/lists.h>
- #include <exec/memory.h>
-
- #include <clib/exec_protos.h>
- #include <clib/alib_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/socket_protos.h>
-
- #include <errno.h>
- #include <inetd.h>
- #include <sys/types.h>
-
- #include <proto/socket.h>
- #include <proto/exec.h>
- #include <sys/errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <sys/syslog.h>
- #include <netdb.h>
-
-
- #include <intuition/intuition.h>
- #include <intuition/intuitionbase.h>
- #include <intuition/gadgetclass.h>
- #include <intuition/screens.h>
- #include <libraries/gadtools.h>
- #include <clib/icon_protos.h>
- #include <clib/wb_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/diskfont_protos.h>
- #include <clib/gadtools_protos.h>
- #include <clib/graphics_protos.h>
-
- #include <pragmas/socket_pragmas.h>
- #include <devices/timer.h>
-
- #include "AmiTrackShared.h"
-
- #define MAX_PING_ERRORS 5
- #define DEFAULT_PING_DELAY 1
- #define DEFAULT_REFRESH_DELAY 5
- #define DEFAULT_AMITRACK_SERVER ""
-
- struct Library * SocketBase = NULL;
-
- struct timerequest *TimerIO = NULL;
- struct MsgPort *TimerMP = NULL;
- struct Message *TimerMSG = NULL;
-
- BOOL BStartedFromWB = FALSE;
- BOOL BSendGoodbye = FALSE; /* TRUE if we think we have a live server, else FALSE */
- int nPort = SERVER_TCP_PORT;
- int nPingInterval = DEFAULT_PING_DELAY, nRefreshInterval = DEFAULT_REFRESH_DELAY;
- int nPingCount = DEFAULT_PING_DELAY, nRefreshCount = DEFAULT_REFRESH_DELAY;
- struct SocketStuff * UDPSocket = NULL;
- struct TimerStuff * Timer = NULL;
- char * szCurrentHostname = NULL, * szCurrentComment = NULL;
- char szMyHostName[100];
- ULONG ulMyIPAddress = 0L;
- char szVersionString[] = "$VER: AmiTrack v1.1", * pcDisplayVersionString;
- void BeAClient(char * szHostName, char * szComment, int nPort);
- void Cleanup(void);
- void debug(int n);
- BOOL SendPacket(struct SocketStuff * sSocket, ULONG ulReqs, char * szComment);
- BOOL ConnectToServer(struct WindowStuff *, struct SocketStuff *, char * szPeerName);
- BOOL PingServer(struct WindowStuff * win, struct SocketStuff * sSocket, char * szComment);
- void DoPeriodicUpdates(struct WindowStuff * win, struct SocketStuff * sSocket, struct TimerStuff * timer);
- int main(int argc, char **argv);
-
-
- /* Data structures for Gadtools GUI */
- struct Library * WorkbenchBase = NULL;
- struct Library * IconBase = NULL;
- struct Library * GraphicsBase = NULL;
- struct Library * IntuitionBase = NULL;
- struct Library * GadToolsBase = NULL;
- struct Library * DiskFontBase = NULL;
-
- struct WindowStuff * TrackWindow = NULL;
- struct Menu *Menu = NULL;
- struct MenuItem *MenuItem = NULL;
-
- /* GUI settings */
- int nWinLeft = 50;
- int nWinTop = 100;
- int nWinWidth = 520;
- int nWinHeight = 200;
- int nMinWinWidth = 300;
- int nMinWinHeight = 120;
-
- #define P_ICONIFY 100
- #define P_ABOUT 101
- #define P_QUIT 102
-
- /* menus */
- struct NewMenu nmMenus[] = {
- NM_TITLE, "Project", NULL, 0L, NULL, NULL,
- NM_ITEM, "About", "O", 0L, NULL, (void *) P_ABOUT,
- NM_ITEM, "Iconify", "I", 0L, NULL, (void *) P_ICONIFY,
- NM_ITEM, NM_BARLABEL, NULL, 0L, NULL, NULL,
- NM_ITEM, "Quit", "Q", 0L, NULL, (void *) P_QUIT,
- NM_END, NULL, NULL, NULL, NULL, NULL
- };
-
-
-
- /* GUI functions */
- struct WindowStuff * SetupTrackWindow(struct WindowStuff *);
- ULONG HandleIDCMP(struct WindowStuff *);
- BOOL UpdateWindow(struct WindowStuff * win, BOOL BFree);
- struct Node * AllocDisplayItem(char * szHostName, ULONG ulIPAddress, ULONG ulHostFieldLen, char * szComment);
- void FreeDisplayList(struct List * list);
- void SetConnectStatus(struct WindowStuff * win, BOOL BNewStatus);
- void StatMessage(char *);
- void FreeDisplayItem(struct Node * current);
- void AttachList(struct WindowStuff * win, BOOL BAttach);
- void PatchDisplayList(struct List * DisplayList, ULONG ulIPAddress, char * szReplaceMe, char * szNewComment);
- struct WindowStuff * Hibernate(struct WindowStuff *, struct SocketStuff * sSocket, struct TimerStuff * timer);
- BOOL CreateTrackMenus(struct WindowStuff * win, BOOL BCreate);
-
- /* ------------ Amiga GUI functions -------------------------- */
-
- #define HSPACE 5
- #define VSPACE 5
- #define PING_BUTTON_TEXT "_Ping"
- #define UPDATE_BUTTON_TEXT "_Refresh"
- #define SERVER_STRING_TEXT "_Server:"
- #define PORT_STRING_TEXT "P_ort:"
- #define COMMENT_STRING_TEXT "_Comment:"
- #define EVERY_TEXT "every"
- #define MINS_TEXT1 "_minutes,"
- #define MINS_TEXT2 "m_inutes."
- #define ALL_BOTTOM_LINE_TEXT "Refresh every 888 minutes, Ping every 888 minutes."
-
-
- /* Iconify yourself and don't wake up until... */
- struct WindowStuff * Hibernate(struct WindowStuff *win, struct SocketStuff * sSocket, struct TimerStuff * timer)
- {
- int nCode;
- struct MsgPort *myport = NULL;
- struct AppIcon *appicon = NULL;
- struct AppMessage *amsg = NULL;
- struct DiskObject *appIconObj = NULL;
- struct List * saveDisplayList;
-
- /* backup--use default icon */
- UNLESS(appIconObj = GetDefDiskObject(WBTOOL)) return(win);
- appIconObj->do_Type = 0L;
-
- if (myport = CreateMsgPort())
- {
- if (appicon = AddAppIconA(0L, 0L, "AmiTrack", myport, NULL, appIconObj, NULL))
- {
- /* Save the display list! */
- saveDisplayList = win->DisplayList;
- win->DisplayList = NULL;
-
- SetupTrackWindow(win);
- while(1)
- {
- nCode = TrackWait(NULL, NULL, Timer, NULL, myport);
- if (nCode & CODE_TIMER_EXPIRED) DoPeriodicUpdates(TrackWindow, sSocket, timer);
- if (nCode & CODE_MSGPORT) break;
- if (nCode == 0) break;
- }
- RemoveAppIcon(appicon);
- win = SetupTrackWindow(NULL);
- AttachList(win,FALSE);
- win->DisplayList = saveDisplayList;
- AttachList(win,TRUE);
- }
- /* Remove any pending messages */
- Forbid();
- while (amsg = (struct AppMessage *) GetMsg(myport)) ReplyMsg((struct Message *)amsg);
- DeleteMsgPort(myport);
- Permit();
-
- FreeDiskObject(appIconObj);
- }
- return(win);
- }
-
- /* To tear down, set BCreate==FALSE */
- BOOL CreateTrackMenus(struct WindowStuff * win, BOOL BCreate)
- {
- UNLESS((win)&&(win->vi)) return(FALSE);
-
- UNLESS(BCreate)
- {
- if (Menu)
- {
- ResetMenuStrip(win->win,Menu);
- FreeMenus(Menu);
- Menu = NULL;
- }
- return(FALSE);
- }
-
- /* Create menus */
- UNLESS((Menu = CreateMenus(nmMenus, TAG_DONE)) &&
- (LayoutMenus(Menu, win->vi, TAG_DONE)))
- return(CreateTrackMenus(win, FALSE));
-
- SetMenuStrip(win->win, Menu);
- return(TRUE);
- }
-
- /* Updates/reupdates the window on creation or after a size change */
- /* If BFree is TRUE, just deallocate anything that was allocated */
- /* Returns the allocated/deallocated state of the window gadgets */
- BOOL UpdateWindow(struct WindowStuff * win, BOOL BFree)
- {
- int nID = 0;
- struct NewGadget ng;
- struct Gadget * gad;
-
- UNLESS((win)&&(win->screen)) return(FALSE);
- /* First deallocate */
- if ((win->win)&&(win->glist)) RemoveGList(win->win, win->glist, -1);
- if (win->glist) {FreeGadgets(win->glist); win->glist = NULL;}
-
- /* Mark all gadgets as free */
- win->ListGadget = win->PingButton =
- win->UpdateButton = win->ServerString =
- win->PortString = win->CommentString =
- win->UpdateIntString = win->PingIntString = NULL;
-
- if (Menu) CreateTrackMenus(win, FALSE);
- if (win->vi) {FreeVisualInfo(win->vi); win->vi = NULL;}
- if (BFree) return(FALSE); /* If we're just freeing, that's all to do */
-
- if (win->win)
- {
- /* erase any gadget imagery */
- EraseRect(win->win->RPort,win->win->BorderLeft, win->win->BorderTop,
- win->win->Width - win->win->BorderRight - 1,
- win->win->Height - win->win->BorderBottom - 1);
- RefreshWindowFrame(win->win);
- }
-
- /* Make everything NULL, etc. */
- memset(&ng, 0, sizeof(ng));
-
- /* Now start allocating */
- UNLESS(win->vi = GetVisualInfo(win->screen,TAG_END)) return(FALSE);
- UNLESS(CreateTrackMenus(win, TRUE)) return(FALSE);
- UNLESS(gad = CreateContext(&win->glist)) return(FALSE);
-
- /* Allocate Server gadget */
- ng.ng_VisualInfo = win->vi;
- ng.ng_TextAttr = &win->font;
- ng.ng_Height = win->font.ta_YSize + VSPACE;
- ng.ng_GadgetText = SERVER_STRING_TEXT;
- ng.ng_LeftEdge += win->screen->WBorLeft + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
- ng.ng_TopEdge = win->screen->WBorTop + win->screen->RastPort.TxHeight + VSPACE;
- ng.ng_Width = ((win->win->Width * 2)/3) - ng.ng_LeftEdge;
- ng.ng_GadgetID = nID++;
- ng.ng_Flags = PLACETEXT_LEFT;
- win->ServerString = gad = CreateGadget(STRING_KIND, gad, &ng, GTST_String, szCurrentHostname, GT_Underscore, '_', TAG_END);
-
- /* Allocate Port gadget */
- ng.ng_GadgetText = PORT_STRING_TEXT;
- ng.ng_LeftEdge += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
- ng.ng_Width = win->win->Width - ng.ng_LeftEdge - win->screen->WBorRight - HSPACE;
- ng.ng_GadgetID = nID++;
- ng.ng_Flags = PLACETEXT_LEFT;
- win->PortString = gad = CreateGadget(INTEGER_KIND, gad, &ng, GTIN_Number, nPort, GT_Underscore, '_', TAG_END);
-
- /* Allocate Comment gadget */
- ng.ng_GadgetText = COMMENT_STRING_TEXT;
- ng.ng_LeftEdge = win->screen->WBorLeft + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
- ng.ng_TopEdge += ng.ng_Height + VSPACE;
- ng.ng_Width = win->win->Width - ng.ng_LeftEdge - win->screen->WBorRight - HSPACE;
- ng.ng_GadgetID = nID++;
- ng.ng_Flags = PLACETEXT_LEFT;
- win->CommentString = gad = CreateGadget(STRING_KIND, gad, &ng, GTST_String, szCurrentComment, GT_Underscore, '_', TAG_END);
-
- /* Allocate Update button */
- ng.ng_GadgetText = UPDATE_BUTTON_TEXT;
- ng.ng_TopEdge += ng.ng_Height + VSPACE;
- ng.ng_LeftEdge = win->screen->WBorLeft + HSPACE;
- ng.ng_Width = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
- ng.ng_Flags = PLACETEXT_IN;
- ng.ng_GadgetID = nID++;
- win->UpdateButton = gad = CreateGadget(BUTTON_KIND, gad, &ng, GT_Underscore, '_', TAG_END);
-
- /* Allocate UpdateInterval string */
- ng.ng_GadgetText = EVERY_TEXT;
- ng.ng_LeftEdge += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
- ng.ng_Width = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
- ng.ng_Flags = PLACETEXT_LEFT;
- ng.ng_GadgetID = nID++;
- win->UpdateIntString = gad = CreateGadget(INTEGER_KIND, gad, &ng, GTIN_Number, nRefreshInterval, GT_Underscore, '_', TAG_END);
-
- /* Allocate Mins text */
- ng.ng_GadgetText = MINS_TEXT1;
- ng.ng_Flags = PLACETEXT_LEFT;
- ng.ng_LeftEdge += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
- ng.ng_Width = 0;
- ng.ng_GadgetID = nID++;
- gad = CreateGadget(TEXT_KIND, gad, &ng, GT_Underscore, '_', TAG_END);
-
- /* Allocate Ping button */
- ng.ng_GadgetText = PING_BUTTON_TEXT;
- ng.ng_Width = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
- ng.ng_Flags = PLACETEXT_IN;
- ng.ng_GadgetID = nID++;
- win->PingButton = gad = CreateGadget(BUTTON_KIND, gad, &ng, GT_Underscore, '_', TAG_END);
-
- /* Allocate PingInterval string */
- ng.ng_GadgetText = EVERY_TEXT;
- ng.ng_LeftEdge += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
- ng.ng_Width = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
- ng.ng_Flags = PLACETEXT_LEFT;
- ng.ng_GadgetID = nID++;
- win->PingIntString = gad = CreateGadget(INTEGER_KIND, gad, &ng, GTIN_Number, nPingInterval, GT_Underscore, '_', TAG_END);
-
- /* Allocate Mins2 text */
- ng.ng_GadgetText = MINS_TEXT2;
- ng.ng_Flags = PLACETEXT_LEFT;
- ng.ng_LeftEdge += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
- ng.ng_Width = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
- ng.ng_GadgetID = nID++;
- gad = CreateGadget(TEXT_KIND, gad, &ng, GT_Underscore, '_', TAG_END);
-
- /* Allocate ListView */
- ng.ng_GadgetText = NULL;
- ng.ng_TextAttr = &win->fixedfont;
- ng.ng_LeftEdge = win->screen->WBorLeft + HSPACE;
- ng.ng_TopEdge += ng.ng_Height + VSPACE;
- ng.ng_Width = win->win->Width - ng.ng_LeftEdge - win->screen->WBorRight - HSPACE;
- ng.ng_Height = win->win->Height - ng.ng_TopEdge - win->screen->WBorBottom - (VSPACE*2);
- win->ListGadget = gad = CreateGadget(LISTVIEW_KIND, gad, &ng, GTLV_ReadOnly, TRUE, GTLV_Labels, win->DisplayList, TAG_END);
-
- /* Attach gadgets to window */
- AddGList(win->win, win->glist, -1, -1, NULL);
- RefreshGList(win->glist, win->win, NULL, -1);
- GT_RefreshWindow(win->win, NULL);
-
- return(TRUE);
- }
-
-
- void AttachList(struct WindowStuff * win, BOOL BAttach)
- {
- if ((win->win)&&(win->ListGadget))
- {
- GT_SetGadgetAttrs(win->ListGadget, win->win, NULL,
- GTLV_Labels, (((BAttach)&&(win->DisplayList))
- ? win->DisplayList : ((struct List *)(~0))), TAG_END);
- }
- }
-
- /* Disables some gadgets if we aren't properly connected */
- void SetConnectStatus(struct WindowStuff * win, BOOL BNewStatus)
- {
- /* If we're not connected, might as well ditch our list */
- if ((win->ListGadget)&&(win->DisplayList)&&(BNewStatus == FALSE))
- {
- AttachList(win, TRUE);
- if (win->DisplayList) FreeDisplayList(win->DisplayList);
- win->DisplayList = NULL;
- AttachList(win, FALSE);
- }
- if (win->PingButton) GT_SetGadgetAttrs(win->PingButton, win->win, NULL, GA_Disabled, !BNewStatus);
- if (win->UpdateButton) GT_SetGadgetAttrs(win->UpdateButton, win->win, NULL, GA_Disabled, !BNewStatus);
- BSendGoodbye = BNewStatus;
- }
-
-
-
-
-
- /* Returns any additional action flags that we want set */
- ULONG HandleIDCMP(struct WindowStuff * win)
- {
- struct IntuiMessage *message;
- ULONG class, code, qual, ulItemCode, ulFlags = 0L;
- struct Gadget * gad;
- struct MenuItem * mItem;
-
- /* Examine pending messages */
- while (message = (struct IntuiMessage *)GetMsg(win->win->UserPort))
- {
- class = message->Class; /* extract needed info from message */
- code = message->Code;
- gad = (struct Gadget *) message->IAddress;
- qual = message->Qualifier;
-
- /* tell Intuition we got the message */
- ReplyMsg((struct Message *)message);
-
- /* see what events occured, take correct action */
- switch(class)
- {
- case IDCMP_CLOSEWINDOW:
- TrackExit("Window closed", RETURN_OK);
- break;
-
- case IDCMP_NEWSIZE:
- UpdateWindow(win,FALSE);
- break;
-
- case IDCMP_INTUITICKS:
- break;
-
- case IDCMP_MOUSEBUTTONS:
- break;
-
- case IDCMP_VANILLAKEY:
- switch(code)
- {
- case 'p': case 'P': ulFlags |= CODE_PING; break;
- case 'r': case 'R': ulFlags |= CODE_REFRESH; break;
- case 's': case 'S': ActivateGadget(win->ServerString, win->win, NULL); break;
- case 'o': case 'O': ActivateGadget(win->PortString, win->win, NULL); break;
- case 'c': case 'C': ActivateGadget(win->CommentString, win->win, NULL); break;
- case 'm': case 'M': ActivateGadget(win->UpdateIntString, win->win, NULL); break;
- case 'i': case 'I': ActivateGadget(win->PingIntString, win->win, NULL); break;
- }
- break;
-
- case IDCMP_GADGETUP:
- if (gad == win->ListGadget) {/* printf("ListGadget\n");*/}
- else if (gad == win->PingButton) ulFlags |= CODE_PING;
- else if (gad == win->CommentString)
- {
- char * szTemp = NULL;
-
- /* Grab and sanitize the new comment */
- ReplaceAllocedString(&szTemp,((struct StringInfo*)win->CommentString->SpecialInfo)->Buffer);
- ReplaceAllocedString(&szCurrentComment, PastSpaces(RemoveUnprintableChars(szTemp)));
- ReplaceAllocedString(&szTemp, NULL);
- GT_SetGadgetAttrs(win->CommentString, win->win, NULL, GTST_String, szCurrentComment);
-
- ulFlags |= CODE_PING;
- AttachList(win,FALSE);
- PatchDisplayList(win->DisplayList, ulMyIPAddress, szMyHostName, szCurrentComment);
- AttachList(win,TRUE);
- }
- else if (gad == win->ServerString)
- {
- char * szTemp = NULL;
-
- /* Grab and sanitize the new server string */
- ReplaceAllocedString(&szTemp,((struct StringInfo*)win->ServerString->SpecialInfo)->Buffer);
- ReplaceAllocedString(&szCurrentHostname, ToLower(PastSpaces(RemoveUnprintableChars(szTemp))));
- ReplaceAllocedString(&szTemp, NULL);
- UNLESS(strcmp(szCurrentHostname,"localhost")) ReplaceAllocedString(&szCurrentHostname, szMyHostName);
- GT_SetGadgetAttrs(win->ServerString, win->win, NULL, GTST_String, szCurrentHostname);
- ulFlags |= CODE_RECONNECT;
- }
- else if (gad == win->PortString)
- {
- nPort = ((struct StringInfo*)win->PortString->SpecialInfo)->LongInt;
- if (nPort == 0)
- {
- nPort = SERVER_TCP_PORT;
- GT_SetGadgetAttrs(win->PortString, win->win, NULL, GTIN_Number, nPort);
- }
- ulFlags |= CODE_RECONNECT;
- }
- else if (gad == win->UpdateButton) ulFlags |= CODE_REFRESH;
- else if (gad == win->UpdateIntString)
- {
- nRefreshCount = nRefreshInterval = ((struct StringInfo*)win->UpdateIntString->SpecialInfo)->LongInt;
- }
- else if (gad == win->PingIntString)
- {
- nPingCount = nPingInterval = ((struct StringInfo*)win->PingIntString->SpecialInfo)->LongInt;
- }
- /* else printf("unknown gadget %p\n",gad); */
-
- break;
-
- case IDCMP_MENUPICK:
- while( code != MENUNULL )
- {
- char szMessage[150];
- mItem = ItemAddress( Menu, code );
-
- ulItemCode = (ULONG) GTMENUITEM_USERDATA(mItem);
- switch(ulItemCode)
- {
- case P_ICONIFY:
- ulFlags |= CODE_ICONIFY;
- break;
-
- case P_ABOUT:
- sprintf(szMessage,"%s\nby Jeremy Friesner\njfriesne@ucsd.edu\nCompiled: %s",
- pcDisplayVersionString,__DATE__);
- MakeReq(NULL,szMessage,"Not Bad");
- break;
- case P_QUIT: TrackExit("Quit requested",RETURN_OK); break;
- }
- code = mItem->NextSelect;
- }
- break;
-
- case IDCMP_REFRESHWINDOW:
- GT_BeginRefresh(win->win);
- GT_EndRefresh(win->win, TRUE);
- break;
-
- default:
- /* printf("handleIDCMP: bad class %lu\n",class); */
- break;
- }
- }
- return(ulFlags);
- }
-
-
- /* Searches the given DisplayList until it finds a string beginning with
- szReplaceMe. It then deletes that node and replaces it with an
- entry composed of the params */
- void PatchDisplayList(struct List * DisplayList, ULONG ulIPAddress, char * szReplaceMe, char * szNewComment)
- {
- struct Node * current, * prev = NULL, * newNode;
- char * pcTemp, * pcSpace;
- int nLen = strlen(szReplaceMe);
- ULONG ulThisIPAddress;
-
- UNLESS(DisplayList) return;
- current = DisplayList->lh_Head;
- while(current->ln_Succ)
- {
- if (pcTemp = (char *)current->ln_Name)
- {
- ulThisIPAddress = (ULONG) *((ULONG *) (current->ln_Name-sizeof(ULONG)-sizeof(ULONG)));
- if (ulIPAddress == ulThisIPAddress)
- {
- /* Figure out the correct padding from the old one */
- UNLESS(pcSpace = strchr(pcTemp,' ')) return;
- while(*pcSpace == ' ') pcSpace++;
- if (newNode = AllocDisplayItem(szReplaceMe, ulIPAddress, ((int)(pcSpace-pcTemp))-1, szNewComment))
- {
- Remove(current);
- Insert(DisplayList, newNode, prev);
- FreeDisplayItem(current);
- }
- return;
- }
- }
- prev = current;
- current = current->ln_Succ;
- }
- }
-
-
- struct WindowStuff * SetupTrackWindow(struct WindowStuff * win)
- {
- if (win)
- {
- /* Free the window */
- UpdateWindow(win,TRUE); /* Free all the gadgets */
- if (win->DisplayList) FreeDisplayList(win->DisplayList);
- if (win->fontdata) CloseFont(win->fontdata);
- if (win->fixedfontdata) CloseFont(win->fixedfontdata);
- if (win->win) CloseWindow(win->win);
- if (win->screen) UnlockPubScreen(NULL,win->screen);
-
- FreeMem(win,sizeof(struct WindowStuff));
- return(NULL);
- }
- else
- {
- UNLESS(win = AllocMem(sizeof(struct WindowStuff), MEMF_CLEAR)) return(NULL);
-
- /* Find the default public screen */
-
- UNLESS(win->screen = LockPubScreen(NULL)) return(SetupTrackWindow(win));
-
- AskFont(&win->screen->RastPort, &win->font);
- UNLESS(win->fontdata = OpenDiskFont(&win->font)) return(SetupTrackWindow(win));
-
- nMinWinHeight = win->screen->WBorTop + win->screen->RastPort.TxHeight + VSPACE + 3*(win->font.ta_YSize + VSPACE + VSPACE) + win->screen->WBorBottom + VSPACE;
- nMinWinWidth = win->screen->WBorLeft + TextLength(&win->screen->RastPort, ALL_BOTTOM_LINE_TEXT, strlen(ALL_BOTTOM_LINE_TEXT)) + (HSPACE * 25) + win->screen->WBorRight;
-
- /* Open the window */
- UNLESS(win->win = OpenWindowTags(NULL,
- WA_Left, nWinLeft,
- WA_Top, nWinTop,
- WA_Width, nMinWinWidth,
- WA_Height, nMinWinHeight * 2,
- WA_MinWidth, nMinWinWidth,
- WA_MinHeight, nMinWinHeight,
- WA_PubScreen, win->screen,
- WA_PubScreenFallBack, TRUE,
- WA_MaxWidth, -1,
- WA_MaxHeight, -1,
- WA_Title, pcDisplayVersionString,
- WA_CloseGadget, TRUE,
- WA_DepthGadget, TRUE,
- WA_SizeGadget, TRUE,
- WA_Activate, TRUE,
- WA_DragBar, TRUE,
- WA_SizeBBottom, TRUE,
- WA_IDCMP, IDCMP_REFRESHWINDOW | IDCMP_CLOSEWINDOW |
- IDCMP_MENUPICK | IDCMP_NEWSIZE | IDCMP_VANILLAKEY |
- BUTTONIDCMP | LISTVIEWIDCMP | STRINGIDCMP,
- TAG_DONE)) return(SetupTrackWindow(win));
-
- AskFont(win->win->RPort, &win->fixedfont);
- UNLESS(win->fixedfontdata = OpenDiskFont(&win->fixedfont)) return(SetupTrackWindow(win));
-
- UNLESS(UpdateWindow(win,FALSE)) return(SetupTrackWindow(win));
- return(win);
- }
- }
-
-
- /* Creates a DisplayList from a ClientList.
- In a DisplayList, each item is an ASCII string.
- There is a ULONG directly before the beginning of each string,
- giving the string's length. */
- struct List * CreateDisplayList(struct ClientList * oldlist)
- {
- ULONG ulMaxHostnameLength = 0, ulTemp;
- struct Client * client;
- struct List * newlist;
- struct Node * newnode;
-
- UNLESS(oldlist) return(NULL);
-
- /* First allocate our new list header */
- UNLESS(newlist = AllocMem(sizeof(struct List), MEMF_CLEAR)) return(NULL);
- NewList(newlist);
-
- /* first find out the length of the longest hostname in the ClientList */
- client = (struct Client *) oldlist->list.lh_Head;
- while(client->node.ln_Succ)
- {
- ulTemp = strlen(client->hostname);
- if (ulTemp > ulMaxHostnameLength) ulMaxHostnameLength = ulTemp;
- client = (struct Client *)client->node.ln_Succ;
- }
-
- /* Now construct the DisplayList, with hostnames padded out appropriately */
- client = (struct Client *) oldlist->list.lh_Head;
- while(client->node.ln_Succ)
- {
- UNLESS(newnode = AllocDisplayItem(client->hostname, client->ulIPAddress, ulMaxHostnameLength, client->comment)) return(newlist);
- AddTail(newlist, newnode);
- client = (struct Client *)client->node.ln_Succ;
- }
- return(newlist);
- }
-
-
- struct Node * AllocDisplayItem(char * szHostName, ULONG ulIPAddress, ULONG ulHostFieldLen, char * szComment)
- {
- struct Node * newnode;
- UBYTE * pubData;
- ULONG ulAllocLength = ulHostFieldLen + strlen(szComment) + 2; /* 2 == space plus NUL */
- char * pcTemp, * pcTemp2;
-
- UNLESS(newnode = AllocMem(sizeof(struct Node), MEMF_ANY)) return(NULL);
- UNLESS(pubData = AllocMem(ulAllocLength + sizeof(ULONG) + sizeof(ULONG), MEMF_ANY))
- {
- FreeMem(newnode, sizeof(struct Node));
- return(NULL);
- }
- memcpy(pubData, &ulIPAddress, sizeof(ULONG));
- pubData += sizeof(ULONG); /* Ignore the IPAddress ULONG from now on... */
- memcpy(pubData, &ulAllocLength, sizeof(ULONG));
- pubData += sizeof(ULONG); /* Ignore the memalloced ULONG from now on... */
- memset(pubData, ' ', ulHostFieldLen+1);
-
- /* like strcpy but without copying the NUL terminal! */
- pcTemp = pubData; pcTemp2 = szHostName;
- while(*pcTemp2)
- {
- *pcTemp = *pcTemp2;
- pcTemp++; pcTemp2++;
- }
- strcpy(&pubData[ulHostFieldLen+1], szComment);
- newnode->ln_Name = pubData;
- return(newnode);
- }
-
-
- void FreeDisplayItem(struct Node * victim)
- {
- ULONG ulLen;
-
- memcpy(&ulLen, victim->ln_Name-sizeof(ULONG), sizeof(ULONG));
- FreeMem(victim->ln_Name-sizeof(ULONG)-sizeof(ULONG), ulLen+sizeof(ULONG)+sizeof(ULONG));
- FreeMem(victim,sizeof(struct Node));
- }
-
-
- /* Frees an allocated DisplayList. */
- void FreeDisplayList(struct List * list)
- {
- struct Node * current;
-
- UNLESS(list) return;
- while(current = RemHead(list)) FreeDisplayItem(current);
- FreeMem(list, sizeof(struct List));
- }
-
-
- void debug(int n)
- {
- printf("enter debug %i ... ",n); fflush(stdout);
- Delay(50);
- printf("continuing.\n"); fflush(stdout);
- }
-
- VOID wbmain(struct WBStartup *wbargv)
- {
- BStartedFromWB = TRUE;
- main(0,NULL);
- }
-
- int main(int argc, char **argv)
- {
- if ((argc == 2)&&(strcmp(argv[1],"?")==0))
- {
- printf("Usage: AmiTrack [ServerName] [Comment] [Port]\n");
- exit(5);
- }
- atexit(Cleanup);
-
- pcDisplayVersionString = &szVersionString[6];
- BeAClient((argc>=2) ? argv[1] : DEFAULT_AMITRACK_SERVER, (argc>=3) ? argv[2] : NULL, (argc>=4) ? atoi(argv[3]) : SERVER_TCP_PORT);
- }
-
-
-
- /* Always called when AmiTrack exits, does any necessary cleanup */
- void Cleanup(void)
- {
- ReplaceAllocedString(&szCurrentHostname, NULL);
- ReplaceAllocedString(&szCurrentComment, NULL);
-
- if (UDPSocket)
- {
- if (BSendGoodbye) SendPacket(UDPSocket, REQ_BYE, NULL);
- SetupSocket(UDPSocket,0,0);
- }
- if (Timer) SetupTimer(Timer);
- if (SocketBase) CloseLibrary(SocketBase);
-
-
- if (TrackWindow) SetupTrackWindow(TrackWindow);
- if (DiskFontBase) CloseLibrary(DiskFontBase);
- if (GadToolsBase) CloseLibrary(GadToolsBase);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
- if (GraphicsBase) CloseLibrary(GraphicsBase);
- if (WorkbenchBase) CloseLibrary(WorkbenchBase);
- if (IconBase) CloseLibrary(IconBase);
- }
-
-
-
-
-
-
-
- /* Act like a client. Connect to szHostName, register yourself
- with this Amiga's IP address, and the given szComment. */
- void BeAClient(char * szHostName, char * szComment, int nPortPref)
- {
- int nCode;
- struct hostent * localhostent;
-
- UNLESS(SocketBase = OpenLibrary("bsdsocket.library", 2))
- TrackExit("Couldn't open socket.library v2+ (is AmiTCP running?)", RETURN_ERROR);
-
- gethostname(szMyHostName, sizeof(szMyHostName));
- if ((szHostName)&&(strcmp(szHostName,"localhost") == 0)) szHostName = szMyHostName;
- localhostent = gethostbyname(szMyHostName);
- if ((localhostent)&&(localhostent->h_addr_list[0]))
- ulMyIPAddress = (ULONG) *((ULONG *)localhostent->h_addr_list[0]);
-
- /* Allocate our own copies of the given strings */
- if (strlen(szHostName) > 0) ReplaceAllocedString(&szCurrentHostname, szHostName);
- ReplaceAllocedString(&szCurrentComment, szComment);
- nPort = nPortPref;
-
- UNLESS(Timer = SetupTimer(NULL))
- TrackExit("Couldn't setup timer.device.",RETURN_ERROR);
-
- UNLESS(WorkbenchBase = OpenLibrary("workbench.library",37))
- TrackExit("Couldn't open icon.library 37+",RETURN_ERROR);
-
- UNLESS(IconBase = OpenLibrary("icon.library",33))
- TrackExit("Couldn't open icon.library 33+",RETURN_ERROR);
-
- UNLESS(GraphicsBase = OpenLibrary("graphics.library", 37))
- TrackExit("Couldn't open graphics.library 37+",RETURN_ERROR);
-
- UNLESS(IntuitionBase = OpenLibrary("intuition.library", 37))
- TrackExit("Couldn't open intuition.library 37+",RETURN_ERROR);
-
- UNLESS(GadToolsBase = OpenLibrary("gadtools.library", 37))
- TrackExit("Couldn't open gadtools.library 37+",RETURN_ERROR);
-
- UNLESS(DiskFontBase = OpenLibrary("diskfont.library", 37))
- TrackExit("Couldn't open diskfont.library 37+",RETURN_ERROR);
-
- UNLESS(TrackWindow = SetupTrackWindow(NULL))
- TrackExit("Couldn't open GUI", RETURN_ERROR);
-
- UNLESS(UDPSocket = SetupSocket(NULL,0,SOCK_DGRAM))
- TrackExit("Couldn't open UDP Socket.",RETURN_ERROR);
-
- if (szCurrentHostname)
- {
- char szMessage[100];
-
- sprintf(szMessage,"Connecting to [%s], port %i",szCurrentHostname, nPort);
- StatMessage(szMessage);
-
- if (ConnectToServer(TrackWindow, UDPSocket, szCurrentHostname))
- {
- PingServer(TrackWindow, UDPSocket, szCurrentComment);
- Signal(FindTask(NULL),SIGBREAKF_CTRL_D); /* Cause myself to show the client list */
- }
- }
- SetTimer(Timer, 60, 0);
- SetConnectStatus(TrackWindow, FALSE); /* Default to not connected yet */
-
- while(nCode = TrackWait(NULL, NULL, Timer, TrackWindow, NULL))
- {
- if (nCode & CODE_WINDOW_EVENT) nCode |= HandleIDCMP(TrackWindow);
- if (nCode & CODE_REFRESH)
- {
- char szMessage[100];
- struct ClientList * test;
-
- if (szCurrentHostname)
- {
- sprintf(szMessage,"Trying to get login list from %s.",szCurrentHostname);
- StatMessage(szMessage);
- }
-
- if (test = GetTrackList(szCurrentHostname, nPort))
- {
- AttachList(TrackWindow, FALSE);
- if (TrackWindow->DisplayList) FreeDisplayList(TrackWindow->DisplayList);
- TrackWindow->DisplayList = CreateDisplayList(test);
- AttachList(TrackWindow, TRUE);
- SetupClientList(test);
- SetConnectStatus(TrackWindow, TRUE);
- StatMessage("Login list refreshed.");
- }
- else
- {
-
- StatMessage("Couldn't get login list from server.");
- SetConnectStatus(TrackWindow, FALSE);
- }
- }
- if (nCode & CODE_RECONNECT)
- {
- char szMessage[100];
-
- if (BSendGoodbye) SendPacket(UDPSocket, REQ_BYE, NULL);
- BSendGoodbye = FALSE;
- SetupSocket(UDPSocket,0,0);
-
- UNLESS(UDPSocket = SetupSocket(NULL,0,SOCK_DGRAM))
- TrackExit("Couldn't reopen UDP Socket.",RETURN_ERROR);
-
- sprintf(szMessage,"Connecting to [%s], port %i",szCurrentHostname, nPort);
- StatMessage(szMessage);
-
- if (ConnectToServer(TrackWindow, UDPSocket, szCurrentHostname))
- {
- sprintf(szMessage,"Connected to %s:%i",szCurrentHostname,nPort);
- StatMessage(szMessage);
- PingServer(TrackWindow, UDPSocket, szCurrentComment);
- Signal(FindTask(NULL),SIGBREAKF_CTRL_D);
- }
- else
- {
-
- if (szCurrentHostname)
- {
- sprintf(szMessage,"Couldn't connect to %s:%i",szCurrentHostname, nPort);
- StatMessage(szMessage);
- }
- SetConnectStatus(TrackWindow,FALSE);
- }
- }
- if (nCode & CODE_PING) PingServer(TrackWindow, UDPSocket, szCurrentComment);
- if (nCode & CODE_TIMER_EXPIRED) DoPeriodicUpdates(TrackWindow, UDPSocket, Timer);
- if (nCode & CODE_ICONIFY) TrackWindow = Hibernate(TrackWindow, UDPSocket, Timer);
- }
- }
-
-
- /* Handle the pings and updates and so on */
- void DoPeriodicUpdates(struct WindowStuff * win, struct SocketStuff * sSocket, struct TimerStuff * timer)
- {
- if ((nPingInterval > 0)&&((--nPingCount) <= 0))
- {
- PingServer(win, sSocket, szCurrentComment);
- nPingCount = nPingInterval;
- }
- if ((nRefreshInterval > 0)&&((--nRefreshCount) <= 0))
- {
- Signal(FindTask(NULL),SIGBREAKF_CTRL_D); /* Cause myself to show the client list */
- nRefreshCount = nRefreshInterval;
- }
- SetTimer(timer, 60, 0);
- }
-
-
- /* Returns FALSE on too many errors, TRUE otherwise */
- BOOL PingServer(struct WindowStuff * win, struct SocketStuff * sSocket, char * szComment)
- {
- static int nNumErrors;
-
- if (SendPacket(sSocket, REQ_COMMENT, szComment))
- {
- if (nNumErrors >= MAX_PING_ERRORS)
- {
- StatMessage("Server ping recovered!");
- SetConnectStatus(TrackWindow, TRUE);
- }
- nNumErrors = 0;
- }
- else if (nNumErrors++ == MAX_PING_ERRORS)
- {
-
- StatMessage("Error: Server ping timeout");
- SetConnectStatus(TrackWindow, FALSE);
- return(FALSE);
- }
- return(TRUE);
- }
-
-
- /* Sends a UDP packet to the server. The first byte
- of the packet is a control byte, after that there
- is just the NULL-terminated string szComment. */
- BOOL SendPacket(struct SocketStuff * sSocket, ULONG ulReqs, char * szComment)
- {
- int nBufLen;
- char * pcBuf;
- BOOL BRet;
-
- UNLESS(szComment) szComment = "";
- nBufLen = sizeof(ULONG) + strlen(szComment) + 1;
-
- /* Allocate and fill out the transfer buffer */
- UNLESS(pcBuf = (char *)AllocMem(nBufLen, MEMF_ANY)) return(FALSE);
- memcpy(&pcBuf[0], &ulReqs, sizeof(ULONG));
- strcpy(&pcBuf[sizeof(ULONG)], szComment);
- BRet = (send(sSocket->fd, (UBYTE *)pcBuf, nBufLen, 0L) == nBufLen);
- FreeMem(pcBuf, nBufLen);
- return(BRet);
- }
-
-
-
- /* Used by the client. Note that this connect() call probably
- won't fail even if the server IS running on the host named
- szPeerName, because UDP sockets are connectionless, and connect()
- does nothing but affect an AmiTCP-internal setting that governs
- where send() will send to when used on this socket. Rather,
- if something goes wrong, subsequent send() calls will return
- errors instead. */
- BOOL ConnectToServer(struct WindowStuff * win, struct SocketStuff * sSocket, char * szPeerName)
- {
- struct hostent * hp;
- char szMessage[100];
-
- UNLESS(szPeerName) return(FALSE);
- UNLESS(hp = gethostbyname(szPeerName))
- {
- sprintf(szMessage, "Name lookup failed for server [%s]",szPeerName);
- StatMessage(szMessage);
- return(FALSE);
- }
- bzero(&sSocket->saAddr, sizeof(struct sockaddr_in));
- bcopy(hp->h_addr, (char *)&sSocket->saAddr.sin_addr, hp->h_length);
- sSocket->saAddr.sin_port = htons(nPort);
- sSocket->saAddr.sin_family = hp->h_addrtype;
-
- UNLESS(connect(sSocket->fd, (struct sockaddr *) &sSocket->saAddr, sizeof(struct sockaddr_in)) >= 0)
- {
- sprintf(szMessage,"Connect to [%s] failed.",szPeerName);
- StatMessage(szMessage);
- return(FALSE);
- }
- return(TRUE);
- }
-
- void StatMessage(char * message)
- {
- static char szMessage[100];
-
- strncpy(szMessage,message,sizeof(szMessage));
- szMessage[99] = 0;
-
- if ((TrackWindow)&&(TrackWindow->win)) SetWindowTitles(TrackWindow->win, szMessage, (char *)~0);
- }